﻿using Hardware.Reactor.Base.Model;
using Hardware.Reactor.Base.Setting;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Hardware.Reactor.Base
{
    public abstract class TempReaderBase : ReactiveObject, ITempReader
    {
        protected SerialPort serialPort = null;
        protected TcpClient tcpClient = null;
        protected ConcurrentQueue<byte[]> receiveQueue = new ConcurrentQueue<byte[]>();
        protected IReactorConfigProvider provider;
        protected CancellationTokenSource CancellationTokenSource => new CancellationTokenSource();
        protected TempReaderBase()
        {
            MessageObservable = this.WhenAnyValue(p => p.Message);
        }
        [Reactive]
        public bool Initialized { get; set; }
        [Reactive]
        public bool Connected { get; set; }
        [Reactive]
        public string Message { get; set; }

        public IObservable<string> MessageObservable { get; }
        [Reactive]
        public Temperature Temperature { get; set; } = new Temperature();
        public ConnectionMode ConnectionMode { get; private set; }

        public bool Init(IReactorConfigProvider provider, ConnectionMode connectionMode = ConnectionMode.串口)
        {
            this.provider = provider;
            this.ConnectionMode = connectionMode;
            bool result = DoInit();//真正的初始化，交给子类完成
            if (result)
            {
                if (connectionMode == ConnectionMode.串口)
                {
                    //订阅串口接收数据的回调函数
                    serialPort.DataReceived += (s, e) =>
                    {
                        Thread.Sleep(25);
                        int length = serialPort.BytesToRead;
                        byte[] buffer = new byte[length];
                        serialPort.Read(buffer, 0, length);//读取缓冲区数据
                        receiveQueue.Enqueue(buffer);//入队
                    };
                }

                Task.Factory.StartNew(Receive);
                Task.Factory.StartNew(Send);
                Task.Factory.StartNew(Analysis);
            }

            return result;
        }

        //MODBUS

        private byte[] command = new byte[] { 0x97, 0x76, 0x00, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, 0x14 };

        /// <summary>
        /// 发送命令的线程
        /// </summary>
        private async void Send()
        {
            while (!CancellationTokenSource.Token.IsCancellationRequested)
            {
                await Task.Delay(500);

                if (!CheckConnection())
                {
                    continue;
                }

                switch (ConnectionMode)
                {
                    case ConnectionMode.串口:
                        serialPort.Write(command, 0, command.Length);
                        break;
                    case ConnectionMode.网口:
                        tcpClient.Client.Send(command);
                        break;
                    default:
                        break;
                }
            }
        }

        private void Receive()
        {
            if (ConnectionMode == ConnectionMode.串口)
                return;

            while (!CancellationTokenSource.Token.IsCancellationRequested)
            {
                try
                {
                    if (tcpClient == null) break;
                    if (tcpClient.Available <= 0)
                    {
                        Task.Delay(1).Wait();
                        continue;
                    }

                    byte[] buffer = new byte[1024];//最大长度
                    int length = tcpClient.Client.Receive(buffer);//阻塞
                    byte[] receiveBytes = buffer.Take(length).ToArray();//实际长度
                    receiveQueue.Enqueue(receiveBytes);//入队
                }
                catch (Exception ex)
                {
                    Message = ex.Message;
                }
            }
        }

        /// <summary>
        /// 解析收到的byte[]数组
        /// </summary>
        private void Analysis()
        {
            while(!CancellationTokenSource.Token.IsCancellationRequested)
            {
                var result = receiveQueue.TryDequeue(out byte[] receiveBytes);
                if (result)
                {
                    DoAnalysis(receiveBytes);
                }
                else
                {
                    Task.Delay(1).Wait();
                }
            }
        }

        private void DoAnalysis(byte[] receiveBytes)
        {
            if(receiveBytes == null) return;
            if(receiveBytes.Length == 0) return;
            if (receiveBytes.Length == 49)
            {
                byte[] v = new byte[4];
                
                v[0] = receiveBytes[24];
                v[1] = receiveBytes[23];
                v[2] = receiveBytes[22];
                v[3] = receiveBytes[21];
                Temperature.RT = BitConverter.ToSingle(v, 0);

                v[0] = receiveBytes[28];
                v[1] = receiveBytes[27];
                v[2] = receiveBytes[26];
                v[3] = receiveBytes[25];
                Temperature.JT1 = BitConverter.ToSingle(v, 0);

                v[0] = receiveBytes[32];
                v[1] = receiveBytes[31];
                v[2] = receiveBytes[30];
                v[3] = receiveBytes[29];
                Temperature.JT2 = BitConverter.ToSingle(v, 0);

            }
        }


        public bool CheckConnection()
        {
            switch (ConnectionMode)
            {
                case ConnectionMode.串口:
                    if (serialPort != null)
                    {
                        Connected = serialPort.IsOpen;
                    }
                    break;
                case ConnectionMode.网口:
                    if (!tcpClient.Connected)
                    {
                        var name = GetType().Name;
                        if(name== "Temp1Reader")
                        {
                            tcpClient.ConnectAsync(provider.ReactorConfig.Temp1ReaderIP, provider.ReactorConfig.Temp1ReaderPort).Wait(3000);
                        }
                        else
                        {
                            tcpClient.ConnectAsync(provider.ReactorConfig.Temp2ReaderIP, provider.ReactorConfig.Temp2ReaderPort).Wait(3000);
                        }
                        Connected = tcpClient.Connected;
                    }
                    break;
                default:
                    break;
            }

            return Connected;
        }

        public void Close()
        {
            CancellationTokenSource.Cancel();

            Task.Factory.StartNew(() =>
            {
                if(tcpClient!=null)
                {
                    tcpClient.Close();
                    tcpClient = null;
                }
            });
        }

        /// <summary>
        /// 父类中的抽象方法，子类必须实现
        /// </summary>
        /// <returns></returns>
        public abstract bool DoInit();

        private bool hasTest = false;

        /// <summary>
        /// 模拟
        /// </summary>
        /// <exception cref="NotImplementedException"></exception>
        public void StartTest()
        {
            if (!hasTest)
            {
                hasTest = true;

                Task.Factory.StartNew(() =>
                {
                    while (!CancellationTokenSource.Token.IsCancellationRequested)
                    {
                        Task.Delay(1000).Wait();

                        Temperature.RT = new Random().Next(20, 60);
                        Task.Delay(1).Wait();
                        Temperature.JT1 = new Random().Next(20, 60);
                        Task.Delay(1).Wait();
                        Temperature.JT2 = new Random().Next(20, 60);
                        
                    }

                });
            }
        }
    }
}
